package com.apigen.platform.service.impl;

import com.apigen.platform.dto.ApiEndpointRequest;
import com.apigen.platform.entity.GenApiEndpoint;
import com.apigen.platform.entity.GenTable;
import com.apigen.platform.entity.GenTableField;
import com.apigen.platform.mapper.GenApiEndpointMapper;
import com.apigen.platform.mapper.GenTableMapper;
import com.apigen.platform.mapper.GenTableFieldMapper;
import com.apigen.platform.service.IApiEndpointService;
import com.apigen.platform.vo.ApiEndpointVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * API端点服务实现类
 *
 * @author API Generator Platform
 * @since 2024-09-24
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiEndpointServiceImpl implements IApiEndpointService {

    private final GenApiEndpointMapper apiEndpointMapper;
    private final GenTableMapper genTableMapper;
    private final GenTableFieldMapper genTableFieldMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createEndpoint(ApiEndpointRequest request) {
        // 验证端点路径唯一性
        if (!isEndpointPathUnique(request.getEndpointPath(), request.getHttpMethod(), 
                request.getProjectId(), null)) {
            throw new RuntimeException("端点路径已存在：" + request.getHttpMethod() + " " + request.getEndpointPath());
        }

        GenApiEndpoint endpoint = new GenApiEndpoint();
        endpoint.setEndpointName(request.getEndpointName());
        endpoint.setEndpointPath(request.getEndpointPath());
        endpoint.setHttpMethod(request.getHttpMethod());
        endpoint.setTableId(request.getTableId());
        endpoint.setDescription(request.getDescription());
        endpoint.setEnablePagination(request.getEnablePagination());
        endpoint.setEnableSorting(request.getEnableSorting());
        endpoint.setEnableFiltering(request.getEnableFiltering());
        endpoint.setResponseFormat(request.getResponseFormat());
        endpoint.setProjectId(request.getProjectId());
        endpoint.setCreatorId(1000L); // TODO: 从当前用户获取

        apiEndpointMapper.insert(endpoint);
        
        log.info("创建API端点成功：{} {}", request.getHttpMethod(), request.getEndpointPath());
        return endpoint.getEndpointId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateEndpoint(ApiEndpointRequest request) {
        if (request.getEndpointId() == null) {
            throw new RuntimeException("端点ID不能为空");
        }

        // 验证端点路径唯一性
        if (!isEndpointPathUnique(request.getEndpointPath(), request.getHttpMethod(), 
                request.getProjectId(), request.getEndpointId())) {
            throw new RuntimeException("端点路径已存在：" + request.getHttpMethod() + " " + request.getEndpointPath());
        }

        GenApiEndpoint endpoint = new GenApiEndpoint();
        endpoint.setEndpointId(request.getEndpointId());
        endpoint.setEndpointName(request.getEndpointName());
        endpoint.setEndpointPath(request.getEndpointPath());
        endpoint.setHttpMethod(request.getHttpMethod());
        endpoint.setTableId(request.getTableId());
        endpoint.setDescription(request.getDescription());
        endpoint.setEnablePagination(request.getEnablePagination());
        endpoint.setEnableSorting(request.getEnableSorting());
        endpoint.setEnableFiltering(request.getEnableFiltering());
        endpoint.setResponseFormat(request.getResponseFormat());
        endpoint.setUpdateTime(LocalDateTime.now());

        int updated = apiEndpointMapper.updateById(endpoint);
        
        log.info("更新API端点成功：{} {}", request.getHttpMethod(), request.getEndpointPath());
        return updated > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteEndpoints(List<Long> endpointIds) {
        try {
            int deleted = apiEndpointMapper.deleteBatchIds(endpointIds);
            log.info("删除{}个API端点成功", deleted);
            return deleted > 0;
        } catch (Exception e) {
            log.error("删除API端点失败：{}", e.getMessage());
            throw new RuntimeException("删除API端点失败：" + e.getMessage());
        }
    }

    @Override
    public ApiEndpointVO getEndpointDetail(Long endpointId) {
        GenApiEndpoint endpoint = apiEndpointMapper.selectById(endpointId);
        if (endpoint == null) {
            throw new RuntimeException("API端点不存在");
        }

        return convertToVO(endpoint);
    }

    @Override
    public Page<ApiEndpointVO> getEndpointList(Long projectId, Long tableId, String httpMethod, Long current, Long size) {
        Page<GenApiEndpoint> page = new Page<>(current, size);
        LambdaQueryWrapper<GenApiEndpoint> queryWrapper = new LambdaQueryWrapper<>();

        if (projectId != null) {
            queryWrapper.eq(GenApiEndpoint::getProjectId, projectId);
        }
        if (tableId != null) {
            queryWrapper.eq(GenApiEndpoint::getTableId, tableId);
        }
        if (StringUtils.hasText(httpMethod)) {
            queryWrapper.eq(GenApiEndpoint::getHttpMethod, httpMethod);
        }

        queryWrapper.orderByDesc(GenApiEndpoint::getCreateTime);

        Page<GenApiEndpoint> endpointPage = apiEndpointMapper.selectPage(page, queryWrapper);

        // 转换为VO
        Page<ApiEndpointVO> resultPage = new Page<>(current, size);
        resultPage.setTotal(endpointPage.getTotal());

        List<ApiEndpointVO> records = endpointPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        resultPage.setRecords(records);
        return resultPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ApiEndpointVO> generateEndpointsByTable(Long tableId, Long projectId) {
        GenTable table = genTableMapper.selectById(tableId);
        if (table == null) {
            throw new RuntimeException("表不存在");
        }

        List<GenApiEndpoint> endpoints = new ArrayList<>();
        String basePath = "/api/" + convertToApiPath(table.getTableName());

        // 生成基础CRUD端点
        // 1. GET - 获取列表
        GenApiEndpoint listEndpoint = createEndpoint(
                "获取" + table.getTableComment() + "列表",
                basePath,
                "GET",
                tableId,
                "分页获取" + table.getTableComment() + "列表",
                projectId,
                true, true, true
        );
        endpoints.add(listEndpoint);

        // 2. POST - 创建
        GenApiEndpoint createEndpoint = createEndpoint(
                "创建" + table.getTableComment(),
                basePath,
                "POST",
                tableId,
                "创建新的" + table.getTableComment(),
                projectId,
                false, false, false
        );
        endpoints.add(createEndpoint);

        // 3. GET - 获取详情
        GenApiEndpoint detailEndpoint = createEndpoint(
                "获取" + table.getTableComment() + "详情",
                basePath + "/{id}",
                "GET",
                tableId,
                "根据ID获取" + table.getTableComment() + "详情",
                projectId,
                false, false, false
        );
        endpoints.add(detailEndpoint);

        // 4. PUT - 更新
        GenApiEndpoint updateEndpoint = createEndpoint(
                "更新" + table.getTableComment(),
                basePath + "/{id}",
                "PUT",
                tableId,
                "根据ID更新" + table.getTableComment(),
                projectId,
                false, false, false
        );
        endpoints.add(updateEndpoint);

        // 5. DELETE - 删除
        GenApiEndpoint deleteEndpoint = createEndpoint(
                "删除" + table.getTableComment(),
                basePath + "/{id}",
                "DELETE",
                tableId,
                "根据ID删除" + table.getTableComment(),
                projectId,
                false, false, false
        );
        endpoints.add(deleteEndpoint);

        // 批量插入
        endpoints.forEach(apiEndpointMapper::insert);

        log.info("为表{}生成{}个API端点", table.getTableName(), endpoints.size());

        return endpoints.stream().map(this::convertToVO).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ApiEndpointVO> batchGenerateEndpoints(List<Long> tableIds, Long projectId) {
        List<ApiEndpointVO> allEndpoints = new ArrayList<>();

        for (Long tableId : tableIds) {
            try {
                List<ApiEndpointVO> endpoints = generateEndpointsByTable(tableId, projectId);
                allEndpoints.addAll(endpoints);
            } catch (Exception e) {
                log.error("为表{}生成API端点失败：{}", tableId, e.getMessage());
            }
        }

        log.info("批量生成API端点完成，共生成{}个端点", allEndpoints.size());
        return allEndpoints;
    }

    @Override
    public Boolean isEndpointPathUnique(String endpointPath, String httpMethod, Long projectId, Long excludeEndpointId) {
        LambdaQueryWrapper<GenApiEndpoint> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GenApiEndpoint::getEndpointPath, endpointPath)
                   .eq(GenApiEndpoint::getHttpMethod, httpMethod)
                   .eq(GenApiEndpoint::getProjectId, projectId);

        if (excludeEndpointId != null) {
            queryWrapper.ne(GenApiEndpoint::getEndpointId, excludeEndpointId);
        }

        long count = apiEndpointMapper.selectCount(queryWrapper);
        return count == 0;
    }

    @Override
    public ApiStatistics getApiStatistics(Long projectId) {
        LambdaQueryWrapper<GenApiEndpoint> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GenApiEndpoint::getProjectId, projectId);

        List<GenApiEndpoint> endpoints = apiEndpointMapper.selectList(queryWrapper);

        Map<String, Long> methodCounts = endpoints.stream()
                .collect(Collectors.groupingBy(GenApiEndpoint::getHttpMethod, Collectors.counting()));

        // 获取有API的表数量
        Set<Long> tablesWithApi = endpoints.stream()
                .map(GenApiEndpoint::getTableId)
                .collect(Collectors.toSet());

        // 获取项目总表数
        LambdaQueryWrapper<GenTable> tableQueryWrapper = new LambdaQueryWrapper<>();
        tableQueryWrapper.eq(GenTable::getProjectId, projectId);
        long totalTables = genTableMapper.selectCount(tableQueryWrapper);

        return new ApiStatistics() {
            @Override
            public Integer getTotalEndpoints() {
                return endpoints.size();
            }

            @Override
            public Integer getGetEndpoints() {
                return methodCounts.getOrDefault("GET", 0L).intValue();
            }

            @Override
            public Integer getPostEndpoints() {
                return methodCounts.getOrDefault("POST", 0L).intValue();
            }

            @Override
            public Integer getPutEndpoints() {
                return methodCounts.getOrDefault("PUT", 0L).intValue();
            }

            @Override
            public Integer getDeleteEndpoints() {
                return methodCounts.getOrDefault("DELETE", 0L).intValue();
            }

            @Override
            public Integer getTablesWithApi() {
                return tablesWithApi.size();
            }

            @Override
            public Integer getTablesWithoutApi() {
                return (int) (totalTables - tablesWithApi.size());
            }
        };
    }

    /**
     * 转换为VO对象
     */
    private ApiEndpointVO convertToVO(GenApiEndpoint endpoint) {
        // 获取关联表信息
        GenTable table = genTableMapper.selectById(endpoint.getTableId());

        return ApiEndpointVO.builder()
                .endpointId(endpoint.getEndpointId())
                .endpointName(endpoint.getEndpointName())
                .endpointPath(endpoint.getEndpointPath())
                .httpMethod(endpoint.getHttpMethod())
                .tableId(endpoint.getTableId())
                .tableName(table != null ? table.getTableName() : null)
                .tableComment(table != null ? table.getTableComment() : null)
                .description(endpoint.getDescription())
                .enablePagination(endpoint.getEnablePagination())
                .enableSorting(endpoint.getEnableSorting())
                .enableFiltering(endpoint.getEnableFiltering())
                .responseFormat(endpoint.getResponseFormat())
                .projectId(endpoint.getProjectId())
                .creatorId(endpoint.getCreatorId())
                .createTime(endpoint.getCreateTime())
                .updateTime(endpoint.getUpdateTime())
                .build();
    }

    /**
     * 创建端点对象
     */
    private GenApiEndpoint createEndpoint(String name, String path, String method, Long tableId,
                                         String description, Long projectId,
                                         Boolean enablePagination, Boolean enableSorting, Boolean enableFiltering) {
        GenApiEndpoint endpoint = new GenApiEndpoint();
        endpoint.setEndpointName(name);
        endpoint.setEndpointPath(path);
        endpoint.setHttpMethod(method);
        endpoint.setTableId(tableId);
        endpoint.setDescription(description);
        endpoint.setEnablePagination(enablePagination);
        endpoint.setEnableSorting(enableSorting);
        endpoint.setEnableFiltering(enableFiltering);
        endpoint.setResponseFormat("JSON");
        endpoint.setProjectId(projectId);
        endpoint.setCreatorId(1000L); // TODO: 从当前用户获取
        return endpoint;
    }

    /**
     * 将表名转换为API路径
     */
    private String convertToApiPath(String tableName) {
        // 移除表前缀
        String apiPath = tableName;
        if (apiPath.startsWith("sys_")) {
            apiPath = apiPath.substring(4);
        } else if (apiPath.startsWith("gen_")) {
            apiPath = apiPath.substring(4);
        }

        // 转换为复数形式
        if (!apiPath.endsWith("s")) {
            apiPath += "s";
        }

        // 转换下划线为连字符
        return apiPath.replace("_", "-");
    }
}

